package com.bicon.botu.core.base.config;

import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.core.base.common.utils.HttpUtil;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.core.base.repository.redis.RedisTemplateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 系统拦截器
 * 1.通过token获取userId
 * 2.权限校验
 * 3.接口加密校验（未开启）
 *
 * @author tandk
 * @date 2017/3/7 0007
 */
@Slf4j
@Component
public class SystemInterceptor implements HandlerInterceptor {

    @Autowired
    RedisHandler redisHandler;

    /**
     * 服务监控接口（不以V开头的都放行）
     */
    private String VERSION = "/V";

    /**
     * 错误接口
     */
    private String ERROR = "/error";

    /**
     * 公共接口，不用登陆
     */
    private String BASE = "/base/";

    /**
     * 账户登录注册等接口
     */
    private String ACCOUNT = "/account/";

    /**
     * 静态接口，不用登陆
     */
    private String STATIC = "/static/";

    /**
     * APP端接口
     */
    private String API = "/api/";

    /**
     * 服务间调用接口
     */
    private String RPC = "/rpc/";

    /**
     * web端调用接口
     */
    private String WEB = "/web/";

    /**
     * 需要登陆，并且需要相应权限才能访问
     */
    private String PERMISSION = "/permission/";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        // 不要每次用都去获取连接
        RedisTemplateUtil redisTemplate = redisHandler.getGlobalRedisTemplate();
        String sourceType = HttpUtil.getSourceType(request);
        String host = HttpUtil.getRemoteHost(request);
        String method = request.getMethod();
        String fullUrl = HttpUtil.getFullUrl(request);
        log.info("【{}_{}_{}_Start】{}", host, sourceType, method, fullUrl);
        String url = request.getRequestURI();
        /**
         * 1、先通过token获取userId：1>如果没有传入token，则过，2>传入token，则需要通过token查询userId
         * 2、传入参数的userId，在控制器中接收
         */
        String token = request.getParameter("token");
        String userId = "";
        if (StringUtils.isNotEmpty(token)) {
            userId = redisTemplate.getStringValue(Constants.BOTU_USER_TOKEN, token);
            request.setAttribute("userId", userId);
        }

        if (url.contains(STATIC) || url.contains(RPC) || url.contains(BASE) || url.contains(ACCOUNT) || !url.startsWith(VERSION)) {
            return true;
        }

        if (url.contains(API)) {
            if (StringUtils.isEmpty(userId)) {
                log.info("【{}_{}_{}_End】[请先登录]{}", host, sourceType, method, fullUrl);
                HttpUtil.printFailMessage(response, new BaseResult(Constants.RESPONSE_CODE_300, Constants.RESPONSE_MESSAGE_300));
                return false;
            }
            // 校验用户是否有访问接口权限
            if (!verifyPermission(userId, fullUrl)) {
                HttpUtil.printFailMessage(response, new BaseResult(Constants.RESPONSE_CODE_302, Constants.RESPONSE_MESSAGE_302));
                return false;
            }
        } else if(url.contains(ERROR)) {
            log.info("【{}_{}_{}_End】[接口不存在]{}", host, sourceType, method, fullUrl);
            HttpUtil.printFailMessage(response, new BaseResult(Constants.RESPONSE_CODE_404, Constants.RESPONSE_MESSAGE_404));
            return false;
        } else {
            // 后台用户校验
            userId = redisTemplate.getStringValue(Constants.BOTU_USER_WEB_TOKEN, token);
            if (StringUtils.isEmpty(userId)) {
                log.info("【{}_{}_{}_End】[请先登录]{}", host, sourceType, method, fullUrl);
                HttpUtil.printFailMessage(response, new BaseResult(Constants.RESPONSE_CODE_300, Constants.RESPONSE_MESSAGE_300));
                return false;
            }
            request.setAttribute("userId", userId);
        }
        return true;
    }

    /**
     * 校验用户是否有访问接口权限
     *
     * @param userId 用户id
     * @param url    请求url地址
     * @return
     */
    private boolean verifyPermission(String userId, String url) {
        // 判断是否为权限接口
        if (url.contains(PERMISSION)) {
            // 获取用户角色列表
            if (redisHandler.getGlobalRedisTemplate().hasKey(Constants.ACCOUNT_ROLE + userId)) {
                List<String> roleList = redisHandler.getGlobalRedisTemplate().getList(Constants.ACCOUNT_ROLE, userId);
                boolean flag = false;
                for (String roleId : roleList) {
                    // 获取角色对应的url地址
                    List<String> resourceList = redisHandler.getGlobalRedisTemplate().getList(Constants.ROLE_RESOURCES, roleId);
                    url = (url.substring(url.indexOf("/", 8))).split("\\?")[0];
                    if (resourceList.contains(url)) {
                        flag = true;
                        break;
                    }
                }
                return flag;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
